/*
 * Copyright (C) 2017 grandcentrix GmbH
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.grandcentrix.thirtyinch.internal;


import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.Lifecycle;
import ohos.aafwk.ability.LifecycleObserver;
import ohos.aafwk.content.Intent;
import ohos.app.AbilityContext;
import ohos.utils.PacMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;

import net.grandcentrix.thirtyinch.TiLog;

/**
 * Keeps track of {@link Ability}s across orientation changes using a id when added via
 * {@link #startTracking(AbilityContext, String)}. When the {@link Ability} finishes the
 * {@link ActivityFinishListener} is triggered.
 */
public class ActivityInstanceObserver implements ILifecycleObserver {
    Ability activity;
    LifecycleObserver mLifecycleObserver;

    /**
     * Callback when an {@link Ability} will be completely destroyed
     */
    public interface ActivityFinishListener {

        /**
         * called when the {@link Ability} finishes completely. Doesn't get called when the
         * Activity changes its configuration
         */
        void onActivityFinished(final Ability activity, final String hostId);
    }

    //@VisibleForTesting
    static final String TI_ACTIVITY_ID_KEY = "ThirtyInch_Activity_id";

    private static final String TAG = ActivityInstanceObserver.class.getSimpleName();

    private ActivityFinishListener mListener;

    private final HashMap<AbilityContext, String> mScopeIdForActivity = new HashMap<>();

    public ActivityInstanceObserver(@NotNull final ActivityFinishListener listener, @NotNull final Ability activity) {
        mListener = listener;
        this.activity = activity;
    }

    @Override
    public void onActivityCreated(Ability ability, PacMap savedInstanceState) {
        this.activity = ability;
        if (savedInstanceState != null) {
            final String scopeId = savedInstanceState.getString(TI_ACTIVITY_ID_KEY);
            if (scopeId != null) {
                // refresh mapping
                mScopeIdForActivity.put(ability, scopeId);
            }
        }
    }

    /**
     * Returns the id provided by {@link #startTracking(AbilityContext, String)}
     *
     * @return a unique id for each {@link Ability} which doesn't change when the {@link Ability}
     * changes its configuration
     */
    @Nullable
    public String getActivityId(final AbilityContext activity) {
        return mScopeIdForActivity.get(activity);
    }

    @Override
    public LifecycleObserver getLifecycleObserver() {
        if (mLifecycleObserver == null) {
            mLifecycleObserver = newLifecycleObserver(this);
        }
        return mLifecycleObserver;
    }

    @Override
    public void onStart(Intent intent) {

    }

    @Override
    public void onInactive() {

    }

    @Override
    public void onActive() {

    }

    @Override
    public void onBackground() {

    }

    @Override
    public void onForeground(Intent intent) {

    }

    @Override
    public void onStop() {
        TiLog.v(TAG, "destroying " + activity);
        TiLog.v(TAG, "isFinishing = " + activity.isTerminating());

        if (activity.isTerminating()) {
            // detected Activity finish, no new Activity instance will be created
            // with savedInstanceState, clear saved presenters
            final String scopeId = mScopeIdForActivity.remove(activity);
            mListener.onActivityFinished(activity, scopeId);
        } else {
            // don't leak old activity instances
            // scopeId is saved in savedInstanceState of finishing Activity.
            mScopeIdForActivity.remove(activity);
        }
        // chad 释放activity
        this.activity = null;
    }


    @Override
    public void onActivitySaveInstanceState(final Ability activity, final PacMap outState) {
        String id = mScopeIdForActivity.get(activity);
        if (id == null) {
            // activity not managed, don't add an id.
            return;
        }
        outState.putString(TI_ACTIVITY_ID_KEY, id);
    }

    /**
     * tracks the Activity over orientation changes using the passed in id. Use
     * {@link #getActivityId(AbilityContext)} to get the current Activity instance with the id
     *
     * @param activity to be tracked {@link Ability}
     * @see #getActivityId(AbilityContext)
     */
    public void startTracking(final AbilityContext activity, final String activityId) {
        mScopeIdForActivity.put(activity, activityId);
    }

    LifecycleObserver newLifecycleObserver(ActivityInstanceObserver observer) {
        return new LifecycleObserver() {
            public void onStart(Intent intent) {
                observer.onStart(intent);
            }

            public void onInactive() {
                observer.onInactive();
            }

            public void onActive() {
                observer.onActive();
            }

            public void onBackground() {
                observer.onBackground();
            }

            public void onForeground(Intent intent) {
                observer.onForeground(intent);
            }

            public void onStop() {
                observer.onStop();
            }
        };
    }
}
